<template>
	<div class="upload-file flex">
		<el-upload
			v-if="!myImgUploadDisabled"
			ref="upload"
			action
			:limit="limit"
			:on-exceed="exceedFn"
			:http-request="uploadFn"
			:show-file-list="false"
			list-type="picture-card"
			accept=".png,.jpg,.jpeg"
			v-bind="$attrs"
		>
			<el-icon><Plus /></el-icon>
			<!-- 提示说明文字 -->
			<template #tip>
				<div style="color: #858ebd">单张图片不超过 {{ fileSize }} M</div>
			</template>
		</el-upload>
		<div v-if="fileList.length" class="f1 w0 overflow-x-auto el-upload-list--picture-card">
			<template v-for="file in fileList" :key="file.id">
				<div class="el-upload-list__item">
					<el-image
						:src="file.downloadUrl"
						:preview-src-list="fileList.map((item) => item.downloadUrl)"
						:initial-index="fileList.findIndex((item) => item.downloadUrl === file.downloadUrl)"
						fit="cover"
						preview-teleported
						hide-on-click-modal
					/>
					<span class="el-upload-list__item-actions" v-if="!myImgUploadDisabled">
						<span class="el-upload-list__item-delete" @click="handleDownload(file)">
							<el-icon><Download /></el-icon>
						</span>
						<span class="el-upload-list__item-delete" @click="handleRemove(file)">
							<el-icon><Delete /></el-icon>
						</span>
					</span>
				</div>
			</template>
		</div>
	</div>
</template>

<script setup name="MyImgUpload">
/**
 * 请求接口
 */
import { rdfileDataUpload } from '@a/public';
import { formContextKey as elFormKey, formItemContextKey as elFormItemKey, genFileId } from 'element-plus';
import { FILE_PREFIX } from '@/config';

const emits = defineEmits(['update:modelValue']),
	elForm = inject(elFormKey, {}),
	elFormItem = inject(elFormItemKey, {}),
	upload = shallowRef(null),
	fileType = ['png', 'jpg', 'jpeg'],
	/***
	 * props
	 * @property {Array} modelValue v-model绑定的值，
	 * @property {Number} fileSize 上传文件大小的限制（默认为10M）
	 * @property {Boolean} download 是否允许下载文件（默认为true）
	 * @property {Boolean} disabled 是否允许操作（上传文件等操作，如果不传默认按照form表单的disabled值
	 * @property {Number} limit 上传附件数量
	 */
	props = defineProps({
		modelValue: [Array, Object],
		fileSize: {
			type: Number,
			default: 10
		},
		download: {
			type: Boolean,
			default: true
		},
		limit: {
			type: Number
		},
		disabled: Boolean
	});

// 是否禁用上传功能
const myImgUploadDisabled = computed(() => props.disabled || elForm?.disabled),
	fileList = ref([]);

watch(
	() => props.modelValue,
	(val = []) => {
		if (!isEqual(val, fileList.value)) {
			const valData = isArray(val) ? val : [val];

			fileList.value =
				valData?.map((item) => ({
					id: item.id,
					downloadUrl: FILE_PREFIX ? `${FILE_PREFIX}${item.storageUrl}` : item.downloadUrl,
					storageUrl: item.storageUrl,
					fileName: item.fileName,
					fileSizeFormat: item.fileSizeFormat,
					fileSize: item.fileSize,
					fileSuffix: item.fileSuffix
				})) || [];
		}
	}
);

watch(
	fileList,
	(val) => {
		emits('update:modelValue', val);
		elForm.validateField(elFormItem.prop);
	},
	{ deep: true }
);

// 文件超出个数限制时的钩子
function exceedFn(files) {
	unref(upload).clearFiles();
	const file = files[0];
	file.uid = genFileId();
	unref(upload).handleStart(file);
	unref(upload).submit();
}

// 上传前校检格式和大小
function handleBeforeUpload(file) {
	// 校检文件类型
	let fileExtension = '';
	if (file.name.lastIndexOf('.') > -1) {
		fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1);
	}
	const isTypeOk = fileType.some((type) => {
		if (file.type.indexOf(type) > -1) return true;
		if (fileExtension && fileExtension.indexOf(type) > -1) return true;
		return false;
	});
	if (!isTypeOk) {
		msgError(`文件格式不正确, 请上传${fileType.join('/')}格式文件!`);
		return false;
	}
	// 校检文件大小
	if (props.fileSize) {
		const isLt = file.size / 1024 / 1024 < props.fileSize;
		if (!isLt) {
			msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
			return false;
		}
	}
	return true;
}

// 文件上传
function uploadFn(data) {
	if (handleBeforeUpload(data.file)) {
		const formdata = new FormData();
		formdata.append('file', data.file);
		rdfileDataUpload(formdata)
			.then((res) => {
				if (props.limit === 1) fileList.value = [];
				fileList.value.push({
					id: res.data.id,
					downloadUrl: FILE_PREFIX ? `${FILE_PREFIX}${res.data.storageUrl}` : res.data.downloadUrl,
					storageUrl: res.data.storageUrl,
					fileName: res.data.fileName.split('.')[0],
					fileSizeFormat: res.data.fileSizeFormat,
					fileSize: res.data.fileSize
				});
			})
			.catch(() => {
				unref(upload).clearFiles();
			});
	} else {
		if (props.limit === 1) fileList.value = [];
	}
}

// 文件下载
function handleDownload(data) {
	downloadGet({ url: data.downloadUrl, fileName: data.fileName });
}

// 删除文件
function handleRemove(file) {
	confirm('此操作将删除该数据, 是否继续?')
		.then(() => {
			unref(upload).clearFiles();
			if (props.limit === 1) {
				fileList.value = [];
			} else {
				const index = fileList.value.findIndex((item) => item.id === file.id);
				fileList.value.splice(index, 1);
			}
			msgSuccess('删除成功');
		})
		.catch(() => {
			msgInfo('已取消删除！');
		});
}
</script>

<style lang="scss" scoped>
.upload-file {
	width: 100%;

	:deep() {
		.is-disabled .el-upload--picture-card {
			display: none !important;
		}
	}

	.el-upload-list--picture-card {
		flex-wrap: nowrap;
		width: 100%;
		margin-left: 8px;

		.el-upload-list__item,
		.el-upload--picture-card {
			-webkit-box-flex: 0;
			-ms-flex-positive: 0;
			flex-grow: 0;
			-ms-flex-negative: 0;
			flex-shrink: 0;
		}

		.el-upload-list__item:hover {
			.el-upload-list__item-actions {
				bottom: 0;
				opacity: 1;
			}
		}

		.el-upload-list__item-actions {
			top: auto;
			bottom: 0;
			bottom: -30px;
			height: 30px;
			opacity: 0;
			transition: all 0.2s;

			span {
				display: inline-block;
			}
		}
	}
}
</style>
